package com.wuliang.generate.common.core.adapter.jpa.impl;


import com.wuliang.generate.common.core.adapter.jpa.EntityFieldTypeAdapter;
import com.wuliang.generate.common.core.basic.BasicEntity;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Predicate;
import java.sql.Date;

/**
 * 实体类字符串字段适配器
 *
 * @author 邬魉
 */
public class StringFieldTypeAdapter implements EntityFieldTypeAdapter<String> {

    private static final String DATE_BETWEEN_REGEX = "<\\d{4}(-\\d{2}){2},\\d{4}(-\\d{2}){2}>";

    private static final String LESS_THAN = "<";

    private static final String LESS_THAN_OR_EQUALS = "<=";

    private static final String BIGGER_THAN = ">";

    private static final String BIGGER_THAN_OR_EQUALS = ">=";

    private static final String NON_SYMBOL = "!";

    private static final String MODULUS = "%";

    @Override
    @SuppressWarnings("unchecked")
    public Predicate toPredicate(Class<? extends BasicEntity> entity, CriteriaBuilder criteriaBuilder, String fieldName,
                                 String fieldValue, From<Object, String> from) {
        if (fieldValue.startsWith(NON_SYMBOL)) {
            // 如果值以 ! 开头则为 [column_name] != ${column_name}
            return criteriaBuilder.notEqual(from.get(fieldName), fieldValue.substring(1));
        } else if (fieldValue.startsWith(LESS_THAN) && fieldValue.endsWith(BIGGER_THAN)) {
            // 调用 between 语句
            if (fieldValue.matches(DATE_BETWEEN_REGEX)) {
                // 如果 要查询的值是日期格式的则以 [,] 切割取值，逗号之前的为起始值，逗号之后的为止，
                fieldValue = fieldValue.substring(1, fieldValue.length() - 1);
                String[] between = fieldValue.split(",");
                // 将切割后的两个值转为 java.sql.Date 类型的日期对象。
                return criteriaBuilder.between(from.get(fieldName), Date.valueOf(between[0]), Date.valueOf(between[1]));
            }
        } else if (fieldValue.startsWith(LESS_THAN)) {
            if (fieldValue.startsWith(LESS_THAN_OR_EQUALS)) {
                fieldValue = fieldValue.substring(2);
                return criteriaBuilder.lessThanOrEqualTo(from.get(fieldName), fieldValue);
            }
            fieldValue = fieldValue.substring(1);
            return criteriaBuilder.lessThan(from.get(fieldName), fieldValue);
        } else if (fieldValue.endsWith(BIGGER_THAN)) {
            if (fieldValue.startsWith(BIGGER_THAN_OR_EQUALS)) {
                fieldValue = fieldValue.substring(2);
                return criteriaBuilder.greaterThanOrEqualTo(from.get(fieldName), fieldValue);
            }
            fieldValue = fieldValue.substring(1);
            return criteriaBuilder.greaterThanOrEqualTo(from.get(fieldName), fieldValue);
        }

        // 否则为 [column_name] like '%${[value]}%'
        return criteriaBuilder.like(from.get(fieldName).as(String.class), MODULUS + fieldValue + MODULUS);
    }
}
